#ifndef __REG_H__
#define __REG_H__

#include "common.h"

enum//enum（枚举）是一种用户定义的数据类型，允许为一组相关的常量赋予名称
{
	R_EAX,
	R_ECX,
	R_EDX,
	R_EBX,
	R_ESP,
	R_EBP,
	R_ESI,
	R_EDI
};
enum
{
	R_AX,
	R_CX,
	R_DX,
	R_BX,
	R_SP,
	R_BP,
	R_SI,
	R_DI
};
enum
{
	R_AL,
	R_CL,
	R_DL,
	R_BL,
	R_AH,
	R_CH,
	R_DH,
	R_BH
};

/* TODO: Re-organize the `CPU_state' structure to match the register
 * encoding scheme in i386 instruction format. For example, if we
 * access cpu.gpr[3]._16, we will get the `bx' register; if we access
 * cpu.gpr[1]._8[1], we will get the 'ch' register. Hint: Use `union'.
 * For more details about the register encoding scheme, see i386 manual.
 */

typedef struct//这里使用了 `union` 联合体。在联合体中，`gpr[8]` 是一个联合体数组，每个元素内部包含了 32 位、16 位和 8 位的变量，可以分别访问寄存器的不同部分。- 同时，`eax, ecx, edx, ebx, esp, ebp, esi, edi` 定义为联合体中的结构成员，与 `gpr[8]` 是共享内存的
{
	union
	{
		union
		{
			uint32_t _32;
			uint16_t _16;
			uint8_t _8[2];
		} gpr[8];

		/* Do NOT change the order of the GPRs' definitions. */

		struct
		{
			uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
		};
	};

	swaddr_t eip;

	union
	{
		struct
		{
			uint32_t CF : 1;//虽然 uint32_t 是 4 字节（32 位），位字段可以在这些字节中安排多个字段。例如，在一个 uint32_t 类型中，你可以定义多个 1 位的标志位，它们会被紧凑地存储在 4 字节中。
			uint32_t pad0 : 1;//pad0、pad1 等填充字段的作用主要是为了在位字段的排列中保证正确的内存对齐或结构体的布局
			uint32_t PF : 1;
			uint32_t pad1 : 1;
			uint32_t AF : 1;
			uint32_t pad2 : 1;
			uint32_t ZF : 1;
			uint32_t SF : 1;
			uint32_t TF : 1;
			uint32_t IF : 1;
			uint32_t DF : 1;
			uint32_t OF : 1;
			uint32_t IOPL : 2;
			uint32_t NT : 1;
			uint32_t pad3 : 1;
			uint16_t pad4;
		};
		uint32_t val;
	} eflags;

} CPU_state;

extern CPU_state cpu;//extern表示外部的变量，即所有文件中都可以使用cpu这个变量，从上面的结构体可以看出，cpu里有9个寄存器(int)和9个标志位

static inline int check_reg_index(int index)
{
	assert(index >= 0 && index < 8);
	return index;
}

#define reg_l(index) (cpu.gpr[check_reg_index(index)]._32)
#define reg_w(index) (cpu.gpr[check_reg_index(index)]._16)
#define reg_b(index) (cpu.gpr[check_reg_index(index) & 0x3]._8[index >> 2])

extern const char *regsl[];
extern const char *regsw[];
extern const char *regsb[];

#endif
